package com.hengpeng.common.config;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Observer;

import org.apache.log4j.Logger;

import com.hengpeng.common.config.monitor.CheckCallBack;
import com.hengpeng.common.config.monitor.FileMonitorObserver;
import com.hengpeng.common.config.monitor.FileObserver;
import com.thoughtworks.xstream.XStream;

/**
 * <pre>
 * xml工具类
 * </pre>
 * @author chenjian
 * @version 1.0, 2010-12-23
 */
public class XmlProvider<T extends Config, K> implements ConfigProvider<K>
{
	private K config;

	private T xmlObj;

	private String filePath;

	private String source;

	private Class<T> clz;

	private FileMonitorObserver<K> fileMonitor;

	private boolean isListenerChange;

	private CheckCallBack<T, K> call;

	Logger logger = Logger.getLogger(this.getClass());

	protected XmlProvider(String path, boolean isListenerChange, CheckCallBack<T, K> call, Class<T> clz)
	{
		super();
		this.filePath = path;
		this.clz = clz;
		this.isListenerChange = isListenerChange;
		this.call = call;
		init();
	}

	protected XmlProvider(String source, CheckCallBack<T, K> call, Class<T> clz)
	{
		super();
		this.source = source;
		this.clz = clz;
		this.isListenerChange = false;
		this.call = call;
		init();
	}

	private void init()
	{
		if (isListenerChange)
		{
			fileMonitor = new FileMonitorObserver<K>(filePath, this);
		}
		this.reloadConfig();
	}

	@Override
	public ConfigProvider<K> getConfigProvider()
	{
		return this;
	}

	@Override
	public Observer getObserver()
	{
		return new FileObserver();
	}

	@Override
	public K getConfig()
	{
		return config;
	}

	@Override
	@SuppressWarnings("unchecked")
	public void reloadConfig()
	{
		logger.info("系统正在装载资源文件");
		synchronized (this)
		{
			config = null;
			XStream xs = new XStream();
			xs.alias(clz.getSimpleName(), clz);
			xs.autodetectAnnotations(true);
			InputStream inStream = null;
			InputStreamReader is = null;
			try
			{
				if (this.filePath != null)
				{
					inStream = new FileInputStream(this.filePath);
					is = new InputStreamReader(inStream, "utf-8");
					xmlObj = clz.cast(xs.fromXML(is));
				}
				else if (source != null)
				{
					xmlObj = clz.cast(xs.fromXML(source));
				}
				if (call != null)
				{
					K k = call.callBack(xmlObj);
					this.config = k;
				}
				else
				{
					this.config = (K) xmlObj;
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
				logger.error("系统配置文件{" + filePath + "}装载失败");
			}
			finally
			{
				try
				{
					if (is != null)
						is.close();
					if (inStream != null)
						inStream.close();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
			if (isListenerChange)
			{
				Long time = 0l;
				try
				{
					time = Long.valueOf(xmlObj.getCheckFileTime());
				}
				catch (Exception ex)
				{
					time = DEFAULT_UPDATE_TIME;
				}
				if (time != null && time > 0)
				{
					fileMonitor.end();
					fileMonitor.start(time * 1000);
				}
				else
				{
					fileMonitor.end();
					fileMonitor.start(DEFAULT_UPDATE_TIME * 1000);
				}
			}
		}
	}

	@Override
	public void setSource(String source)
	{
		this.source = source;
	}
}